<template>
  <div class="p-8 max-w-3xl mx-auto">
    <h1 class="text-2xl font-bold mb-4">哈希生成器</h1>
    <p class="text-gray-600 mb-6">在浏览器中生成文本的哈希值（支持 MD5、SHA-1、SHA-256、SHA-384、SHA-512）。所有处理均在本地完成，隐私安全。</p>

    <div class="mb-4">
      <label class="block text-sm font-medium text-gray-700 mb-2">输入文本</label>
      <textarea
        v-model="text"
        rows="6"
        class="w-full px-4 py-3 border border-gray-200 rounded-lg focus:outline-none focus:border-blue-500"
        placeholder="在这里输入要计算哈希的文本..."
      ></textarea>
    </div>

    <div class="flex items-center space-x-3 mb-4">
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-2">算法</label>
        <select v-model="algorithm" class="px-3 py-2 border rounded-lg focus:outline-none">
          <option v-for="a in algorithms" :key="a" :value="a">{{ a }}</option>
        </select>
      </div>

      <div class="mt-6 flex items-center space-x-2">
        <button @click="generateHash" :disabled="processing" class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-md shadow-sm hover:opacity-95">
          <span v-if="!processing">生成</span>
          <span v-else>生成中...</span>
        </button>

        <button @click="clearAll" class="inline-flex items-center px-4 py-2 border border-gray-200 rounded-md text-sm">清空</button>
      </div>
    </div>

    <div v-if="result !== ''" class="mb-6">
      <label class="block text-sm font-medium text-gray-700 mb-2">结果（{{ algorithm }}）</label>
      <div class="relative">
        <pre class="p-4 bg-gray-50 rounded-lg overflow-x-auto text-sm font-mono">{{ result }}</pre>
        <div class="absolute top-2 right-2 flex space-x-2">
          <button @click="copyResult" class="px-3 py-1 bg-blue-500 text-white rounded text-sm">复制</button>
        </div>
      </div>
    </div>

    <NuxtLink to="/generator-tools" class="text-blue-600 hover:underline">返回生成工具列表</NuxtLink>
  </div>
</template>

<script setup>
import { ref } from 'vue'

useHead({ title: '哈希生成器 - 八八在线工具' })

const text = ref('')
const algorithm = ref('SHA-256')
const algorithms = ['MD5', 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512']
const result = ref('')
const processing = ref(false)

const generateHash = async () => {
  if (!text.value) {
    result.value = ''
    return
  }

  processing.value = true
  try {
    if (algorithm.value === 'MD5') {
      // 使用内置的 JS 实现快速计算 MD5（本实现轻量且适用于浏览器）
      result.value = md5(text.value)
    } else {
      // Web Crypto 支持的算法： 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'
      result.value = await digestHex(algorithm.value.replace('-', '-'))
    }
  } catch (e) {
    console.error(e)
    result.value = '计算错误：' + (e && e.message ? e.message : String(e))
  } finally {
    processing.value = false
  }
}

const clearAll = () => {
  text.value = ''
  result.value = ''
}

const copyResult = async () => {
  if (!result.value) return
  try {
    await navigator.clipboard.writeText(result.value)
    // 简单提示：使用浏览器控制台和短暂的视觉反馈可选（这里不增加全局通知依赖）
    // 也可以考虑使用小的 state 来显示“已复制”提示
    // 这里给出控制台提示以便开发调试
    console.log('已复制到剪贴板')
  } catch (e) {
    console.error('复制失败', e)
  }
}

async function digestHex(algo) {
  const enc = new TextEncoder()
  const data = enc.encode(text.value)
  const subtleAlgo = algo // already 'SHA-1' or 'SHA-256' etc
  const buf = await crypto.subtle.digest(subtleAlgo, data)
  return bufferToHex(buf)
}

function bufferToHex(buffer) {
  const bytes = new Uint8Array(buffer)
  const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('')
  return hex
}

// --- 简单的 MD5 实现（来源：基于常见开源实现的轻量封装） ---
// 说明：此函数只为浏览器端快速计算 MD5 字符串使用，适配当前项目无需安装额外依赖。
function md5(message) {
  function rotateLeft(lValue, iShiftBits) {
    return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits))
  }

  function addUnsigned(lX, lY) {
    const lX4 = lX & 0x40000000
    const lY4 = lY & 0x40000000
    const lX8 = lX & 0x80000000
    const lY8 = lY & 0x80000000
    const lResult = (lX & 0x3fffffff) + (lY & 0x3fffffff)
    if (lX4 & lY4) return lResult ^ 0x80000000 ^ lX8 ^ lY8
    if (lX4 | lY4) {
      if (lResult & 0x40000000) return lResult ^ 0xc0000000 ^ lX8 ^ lY8
      else return lResult ^ 0x40000000 ^ lX8 ^ lY8
    }
    return lResult ^ lX8 ^ lY8
  }

  function f(x, y, z) { return (x & y) | (~x & z) }
  function g(x, y, z) { return (x & z) | (y & ~z) }
  function h(x, y, z) { return x ^ y ^ z }
  function i(x, y, z) { return y ^ (x | ~z) }

  function ff(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(f(b, c, d), x), ac))
    return addUnsigned(rotateLeft(a, s), b)
  }

  function gg(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(g(b, c, d), x), ac))
    return addUnsigned(rotateLeft(a, s), b)
  }

  function hh(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(h(b, c, d), x), ac))
    return addUnsigned(rotateLeft(a, s), b)
  }

  function ii(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(i(b, c, d), x), ac))
    return addUnsigned(rotateLeft(a, s), b)
  }

  function convertToWordArray(str) {
    const lWordCount = []
    const lMessageLength = str.length
    let lNumberOfWords_temp1 = lMessageLength + 8
    let lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64
    const lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16
    for (let i = 0; i < lNumberOfWords; i++) lWordCount[i] = 0
    let lBytePosition = 0
    let lByteCount = 0
    while (lByteCount < lMessageLength) {
      const j = (lByteCount - (lByteCount % 4)) / 4
      lBytePosition = (lByteCount % 4) * 8
      lWordCount[j] = lWordCount[j] | (str.charCodeAt(lByteCount) << lBytePosition)
      lByteCount++
    }
    const j = (lByteCount - (lByteCount % 4)) / 4
    lBytePosition = (lByteCount % 4) * 8
    lWordCount[j] = lWordCount[j] | (0x80 << lBytePosition)
    lWordCount[lNumberOfWords - 2] = lMessageLength << 3
    lWordCount[lNumberOfWords - 1] = lMessageLength >>> 29
    return lWordCount
  }

  function wordToHex(lValue) {
    let wordToHexValue = ""
    for (let i = 0; i <= 3; i++) {
      const byte = (lValue >>> (i * 8)) & 255
      let hex = byte.toString(16)
      if (hex.length === 1) hex = '0' + hex
      wordToHexValue += hex
    }
    return wordToHexValue
  }

  // UTF8 encode
  function utf8Encode(str) {
    return unescape(encodeURIComponent(str))
  }

  let x = []
  let k, AA, BB, CC, DD, a, b, c, d
  const S11 = 7, S12 = 12, S13 = 17, S14 = 22
  const S21 = 5, S22 = 9, S23 = 14, S24 = 20
  const S31 = 4, S32 = 11, S33 = 16, S34 = 23
  const S41 = 6, S42 = 10, S43 = 15, S44 = 21

  const msg = utf8Encode(message)
  x = convertToWordArray(msg)
  a = 0x67452301
  b = 0xefcdab89
  c = 0x98badcfe
  d = 0x10325476

  for (k = 0; k < x.length; k += 16) {
    AA = a
    BB = b
    CC = c
    DD = d
    a = ff(a, b, c, d, x[k + 0], S11, 0xd76aa478)
    d = ff(d, a, b, c, x[k + 1], S12, 0xe8c7b756)
    c = ff(c, d, a, b, x[k + 2], S13, 0x242070db)
    b = ff(b, c, d, a, x[k + 3], S14, 0xc1bdceee)
    a = ff(a, b, c, d, x[k + 4], S11, 0xf57c0faf)
    d = ff(d, a, b, c, x[k + 5], S12, 0x4787c62a)
    c = ff(c, d, a, b, x[k + 6], S13, 0xa8304613)
    b = ff(b, c, d, a, x[k + 7], S14, 0xfd469501)
    a = ff(a, b, c, d, x[k + 8], S11, 0x698098d8)
    d = ff(d, a, b, c, x[k + 9], S12, 0x8b44f7af)
    c = ff(c, d, a, b, x[k + 10], S13, 0xffff5bb1)
    b = ff(b, c, d, a, x[k + 11], S14, 0x895cd7be)
    a = ff(a, b, c, d, x[k + 12], S11, 0x6b901122)
    d = ff(d, a, b, c, x[k + 13], S12, 0xfd987193)
    c = ff(c, d, a, b, x[k + 14], S13, 0xa679438e)
    b = ff(b, c, d, a, x[k + 15], S14, 0x49b40821)
    a = gg(a, b, c, d, x[k + 1], S21, 0xf61e2562)
    d = gg(d, a, b, c, x[k + 6], S22, 0xc040b340)
    c = gg(c, d, a, b, x[k + 11], S23, 0x265e5a51)
    b = gg(b, c, d, a, x[k + 0], S24, 0xe9b6c7aa)
    a = gg(a, b, c, d, x[k + 5], S21, 0xd62f105d)
    d = gg(d, a, b, c, x[k + 10], S22, 0x02441453)
    c = gg(c, d, a, b, x[k + 15], S23, 0xd8a1e681)
    b = gg(b, c, d, a, x[k + 4], S24, 0xe7d3fbc8)
    a = gg(a, b, c, d, x[k + 9], S21, 0x21e1cde6)
    d = gg(d, a, b, c, x[k + 14], S22, 0xc33707d6)
    c = gg(c, d, a, b, x[k + 3], S23, 0xf4d50d87)
    b = gg(b, c, d, a, x[k + 8], S24, 0x455a14ed)
    a = gg(a, b, c, d, x[k + 13], S21, 0xa9e3e905)
    d = gg(d, a, b, c, x[k + 2], S22, 0xfcefa3f8)
    c = gg(c, d, a, b, x[k + 7], S23, 0x676f02d9)
    b = gg(b, c, d, a, x[k + 12], S24, 0x8d2a4c8a)
    a = hh(a, b, c, d, x[k + 5], S31, 0xfffa3942)
    d = hh(d, a, b, c, x[k + 8], S32, 0x8771f681)
    c = hh(c, d, a, b, x[k + 11], S33, 0x6d9d6122)
    b = hh(b, c, d, a, x[k + 14], S34, 0xfde5380c)
    a = hh(a, b, c, d, x[k + 1], S31, 0xa4beea44)
    d = hh(d, a, b, c, x[k + 4], S32, 0x4bdecfa9)
    c = hh(c, d, a, b, x[k + 7], S33, 0xf6bb4b60)
    b = hh(b, c, d, a, x[k + 10], S34, 0xbebfbc70)
    a = hh(a, b, c, d, x[k + 13], S31, 0x289b7ec6)
    d = hh(d, a, b, c, x[k + 0], S32, 0xeaa127fa)
    c = hh(c, d, a, b, x[k + 3], S33, 0xd4ef3085)
    b = hh(b, c, d, a, x[k + 6], S34, 0x04881d05)
    a = hh(a, b, c, d, x[k + 9], S31, 0xd9d4d039)
    d = hh(d, a, b, c, x[k + 12], S32, 0xe6db99e5)
    c = hh(c, d, a, b, x[k + 15], S33, 0x1fa27cf8)
    b = hh(b, c, d, a, x[k + 2], S34, 0xc4ac5665)
    a = ii(a, b, c, d, x[k + 0], S41, 0xf4292244)
    d = ii(d, a, b, c, x[k + 7], S42, 0x432aff97)
    c = ii(c, d, a, b, x[k + 14], S43, 0xab9423a7)
    b = ii(b, c, d, a, x[k + 5], S44, 0xfc93a039)
    a = ii(a, b, c, d, x[k + 12], S41, 0x655b59c3)
    d = ii(d, a, b, c, x[k + 3], S42, 0x8f0ccc92)
    c = ii(c, d, a, b, x[k + 10], S43, 0xffeff47d)
    b = ii(b, c, d, a, x[k + 1], S44, 0x85845dd1)
    a = ii(a, b, c, d, x[k + 8], S41, 0x6fa87e4f)
    d = ii(d, a, b, c, x[k + 15], S42, 0xfe2ce6e0)
    c = ii(c, d, a, b, x[k + 6], S43, 0xa3014314)
    b = ii(b, c, d, a, x[k + 13], S44, 0x4e0811a1)
    a = ii(a, b, c, d, x[k + 4], S41, 0xf7537e82)
    d = ii(d, a, b, c, x[k + 11], S42, 0xbd3af235)
    c = ii(c, d, a, b, x[k + 2], S43, 0x2ad7d2bb)
    b = ii(b, c, d, a, x[k + 9], S44, 0xeb86d391)
    a = addUnsigned(a, AA)
    b = addUnsigned(b, BB)
    c = addUnsigned(c, CC)
    d = addUnsigned(d, DD)
  }

  const temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d)
  return temp.toLowerCase()
}
</script>

<style scoped>
/* 保持风格简洁，使用全局 Tailwind 样式 */
</style>
